Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ


Displaying Rendered β€’ View raw β€’ Download

specs/20260507-161758-node-list-layout/data-model.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 4.60 KB

Data Model β€” Node List Layout

Overview

The Node List Layout feature does not introduce new database entities. It adds preference keys to DataStore and a density enum that controls how existing T383838Node model data is rendered. The data model is entirely read-only from the layout perspective β€” node data comes from the existing Room KMP pipeline.

Entity Relationship

T282828
erDiagram
DataStore ||--o{ NodeListLayoutPreferences : stores
NodeListLayoutPreferences ||--|| NodeListDensity : selects
NodeListDensity ||--|| NodeItem : "renders (COMPLETE)"
NodeListDensity ||--|| NodeItemCompact : "renders (COMPACT)"
NodeItemCompact ||--o{ CompactToggle : "visibility driven by"
NodeItem }o--|| Node : reads
NodeItemCompact }o--|| Node : reads
Node ||--|| NodeEntity : "backed by"

Density Enum

T282828
Tff7b72package T7ee787org.meshtastic.feature.node.model

Tff7b72enum Tff7b72class T56d364NodeListDensity Tb4b4b4{
Te6edf3COMPLETETb4b4b4,
Te6edf3COMPACTTb4b4b4;
Tb4b4b4}


β€’ Persisted as a T383838String (enum name) in DataStore under key T383838nodeListDensity.
β€’ Default: T383838COMPLETE.

Preference Keys

T282828
Tff7b72package T7ee787org.meshtastic.core.prefs.ui

Tff7b72enum Tff7b72class T56d364NodeListLayoutPreferencesTb4b4b4(Tff7b72val Te6edf3keyTb4b4b4: Tffa657StringTb4b4b4, Tff7b72val Te6edf3defaultValueTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3SHOW_POWERTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowPowerTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_LAST_HEARDTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowLastHeardTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3LAST_HEARD_RELATIVETb4b4b4(Ta5d6ff"Ta5d6fflastHeardIsRelativeTa5d6ff"Tb4b4b4, Tff7b72falseTb4b4b4)Tb4b4b4,
Te6edf3SHOW_LOCATIONTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowLocationTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_HOPSTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowHopsTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_SIGNALTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowSignalTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_CHANNELTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowChannelTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_ROLETb4b4b4(Ta5d6ff"Ta5d6ffshouldShowRoleTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_TELEMETRYTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowTelemetryTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4}


Preference Access Pattern

Each key is exposed as a T383838StateFlow<Boolean> in T383838UiPrefsImpl:

T282828
Tff7b72val Te6edf3shouldShowPowerTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3dataStoreTb4b4b4.Te6edf3data
Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTff7b72[Te6edf3booleanPreferencesKeyTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowPowerTa5d6ff"Tb4b4b4)Tff7b72] Tff7b72?: Tff7b72true Tb4b4b4}
Tb4b4b4.Te6edf3stateInTb4b4b4(Te6edf3scopeTb4b4b4, Te6edf3SharingStartedTb4b4b4.Te6edf3EagerlyTb4b4b4, Tff7b72trueTb4b4b4)


The density preference follows the same pattern but maps to the enum:

T282828
Tff7b72val Te6edf3nodeListDensityTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3NodeListDensityTff7b72> Tff7b72= Te6edf3dataStoreTb4b4b4.Te6edf3data
Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3prefs Tff7b72-Tff7b72>
Tff7b72val Te6edf3name Tff7b72= Te6edf3prefsTff7b72[Te6edf3stringPreferencesKeyTb4b4b4(Ta5d6ff"Ta5d6ffnodeListDensityTa5d6ff"Tb4b4b4)Tff7b72] Tff7b72?: Ta5d6ff"Ta5d6ffCOMPLETETa5d6ff"
Te6edf3NodeListDensityTb4b4b4.Te6edf3valueOfTb4b4b4(Te6edf3nameTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3stateInTb4b4b4(Te6edf3scopeTb4b4b4, Te6edf3SharingStartedTb4b4b4.Te6edf3EagerlyTb4b4b4, Te6edf3NodeListDensityTb4b4b4.Te6edf3COMPLETETb4b4b4)


Node Data Fields Used by Layout

The layout reads from the existing T383838Node model in T383838core:model. No new fields are added.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Field β”‚ Type β”‚ Used By β”‚ Condition β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838longName β”‚ T383838String? β”‚ Both β”‚ Always shown β”‚
β”‚ T383838shortName β”‚ T383838String? β”‚ Both β”‚ NodeChip avatar β”‚
β”‚ T383838lastHeard β”‚ T383838Long β”‚ Both β”‚ Non-zero, not > 1 year future β”‚
β”‚ T383838hopsAway β”‚ T383838Int β”‚ Both β”‚ T383838> 0 for hop count, T383838== 0 for signal β”‚
β”‚ T383838snr β”‚ T383838Float β”‚ Both β”‚ T383838!= 0 and T383838!viaMqtt β”‚
β”‚ T383838rssi β”‚ T383838Int β”‚ Both β”‚ Signal quality via T383838determineSignalQuality(snr, r… β”‚
β”‚ T383838batteryLevel β”‚ T383838Int? β”‚ Both β”‚ Non-null β”‚
β”‚ T383838channel β”‚ T383838Int β”‚ Both β”‚ T383838> 0 β”‚
β”‚ T383838position β”‚ T383838Position? β”‚ Both β”‚ Non-null, valid lat/lon β”‚
β”‚ T383838role β”‚ T383838DeviceRole β”‚ Both β”‚ Always (defaults to 0) β”‚
β”‚ T383838viaMqtt β”‚ T383838Boolean β”‚ Both β”‚ Signal exclusion gate β”‚
β”‚ T383838isFavorite β”‚ T383838Boolean β”‚ Both β”‚ Star icon β”‚
β”‚ T383838hasPositionLog β”‚ T383838Boolean β”‚ Both β”‚ Log icon visibility β”‚
β”‚ T383838hasEnvironmentLog β”‚ T383838Boolean β”‚ Both β”‚ Log icon visibility β”‚
β”‚ T383838hasDetectionSensorLog β”‚ T383838Boolean β”‚ Both β”‚ Log icon visibility β”‚
β”‚ T383838hasTracerouteLog β”‚ T383838Boolean β”‚ Both β”‚ Log icon visibility β”‚
β”‚ T383838hasDeviceMetricsLog β”‚ T383838Boolean β”‚ Both β”‚ Log icon visibility β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Adaptive Chip Sizing

The compact T383838NodeChip size is derived from a T383838lineCount property:

T282828
Tff7b72val Te6edf3lineCountTb4b4b4: Tffa657Int Tff7b72= Te6edf3buildList Tb4b4b4{
Te6edf3addTb4b4b4(T79c0ff1Tb4b4b4) T8b949e// Row 1: name β€” always present
Tff7b72if Tb4b4b4(Te6edf3shouldShowLastHeardTb4b4b4) Te6edf3addTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3shouldShowLocation Tff7b72|Tff7b72| Te6edf3shouldShowHops Tff7b72|Tff7b72| Te6edf3shouldShowSignal Tff7b72|Tff7b72|
Te6edf3shouldShowChannel Tff7b72|Tff7b72| Te6edf3shouldShowRole Tff7b72|Tff7b72| Te6edf3shouldShowTelemetryTb4b4b4) Te6edf3addTb4b4b4(T79c0ff1Tb4b4b4)
Tb4b4b4}Tb4b4b4.Te6edf3size

Tff7b72val Te6edf3chipSizeTb4b4b4: Te6edf3Dp Tff7b72= Te6edf3maxTb4b4b4(T79c0ff3T79c0ff6.Te6edf3dpTb4b4b4, Te6edf3minTb4b4b4(T79c0ff7T79c0ff0.Te6edf3dpTb4b4b4, T79c0ff2T79c0ff4.Te6edf3dp Tff7b72* Te6edf3lineCountTb4b4b4)Tb4b4b4)


β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ lineCount β”‚ Chip Size β”‚ Active Rows β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 1 β”‚ 36.dp β”‚ Name only β”‚
β”‚ 2 β”‚ 48.dp β”‚ Name + last heard OR Name + combined β”‚
β”‚ 3 β”‚ 70.dp β”‚ Name + last heard + combined β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Validation Rules

β€’ T383838nodeListDensity must be a valid T383838NodeListDensity enum name. Invalid values fall back to T383838COMPLETE.
β€’ T383838lastHeardIsRelative is functionally irrelevant when T383838shouldShowLastHeard is T383838false (the UI disables the toggle).
β€’ All boolean preferences default to T383838true except T383838lastHeardIsRelative which defaults to T383838false.
β€’ The layout never writes to T383838Node data β€” all mutations flow through the existing packet processing pipeline.

Served by rngit 1.5.0 - Generated in 0.07s